/*
* Copyright (c) 2025 Huawei Device Co., Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including but not limited to the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to provide persons with access to the Software
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGE OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

import React, { useEffect, useRef, useState, useContext, useMemo } from "react";
import { useNavigate } from "react-router-dom";
import { useSelector, useDispatch } from "react-redux";
import { RootState, AppDispatch } from "../../store";
import { addMusiclist } from "../../store/musicSlice";
import { PlayerContext } from "../../context/PlayerContext";
import repeatIcon from "../../assets/images/repeat.svg";
import leftIcon from "../../assets/images/left.svg";
import pauseIcon from "../../assets/images/pause.svg";
import playIcon from "../../assets/images/play.svg";
import forwardIcon from "../../assets/images/forward_end_fill.svg";
import noteListIcon from "../../assets/images/music_note_list.svg";
import sharePlayIcon from "../../assets/images/share_play.svg";
import bellIcon from "../../assets/images/bell.svg";
import arrowDownCircleIcon from "../../assets/images/arrow_down_circle.svg";
import dotIcon from "../../assets/images/dot.svg";
import { useInteraction } from "../../utils/useInteraction";

import "./index.less";

interface MusicPlayerProps {
  deviceType?: string;
  isPlay?: string;
  musicId?: number;
  musicListNum?: number;
  onUpdateMusic?: (musicId: number) => void;
  onUpdateIsPlay?: (isPlay: string) => void;
}

const formatTime = (time: number) => {
  const minutes = Math.floor(time / 60);
  const seconds = Math.floor(time % 60);
  return `${minutes}:${seconds < 10 ? "0" : ""}${seconds}`;
};

const MusicPlayer: React.FC<MusicPlayerProps> = ({
  deviceType = "mobile",
  isPlay: propIsPlay = 'pause',
  musicId: propMusicId = 1,
  musicListNum = 50,
  onUpdateMusic,
  onUpdateIsPlay,
}) => {
  const navigate = useNavigate();
  const musicList = useSelector((state: RootState) => state.music.musicList);
  const { player } = useContext(PlayerContext);

  const [isPlay, setIsPlay] = useState<string>(propIsPlay);
  const [musicId, setMusicId] = useState<number>(propMusicId);
  const [musicTime, setMusicTime] = useState<string>("00:00");
  const [musicPlayTime, setMusicPlayTime] = useState<string>("00:00");
  const [getWidth, setGetWidth] = useState<number>(0);
  const [getOffLeft, setgetOffLeft] = useState<number>(0);

  const scheduleRef = useRef<HTMLSpanElement>(null);
  const scheduleWidth = useRef<number>(0);
  const startX = useRef<number>(0);

  const progressRef = useInteraction({
    handlers: {
      onClick: (e: any) => handleClick(e),
      onScroll: (e: any) => handleScrollStart(e),

    },
    configs: {
      enableClick: true,
      enableScroll: true,
    },
  });

  // 初始化
  useEffect(() => {
    player.seekTo(0);
    const current = musicList.find((item) => item.id === Number(musicId));

    if (isPlay === 'play' && Number(musicId) === current?.id) {
      player.play();
      player.onTimeUpdate(handleTimeUpdate);
    } else {
      player.seekTo(0);
      setIsPlay('pause');
    }
    const timer = setTimeout(() => {
      if (scheduleRef.current) {
        startX.current = scheduleRef.current.getBoundingClientRect().left;
        const style = window.getComputedStyle(scheduleRef.current);
        scheduleWidth.current = parseFloat(style.width);
      }
      setMusicTime(formatTime(player.getDuration()));
      if (player.getCurrentTime() > 0 && isPlay === 'pause') {
        const progressPercentage =
          (player.getCurrentTime() / player.getDuration()) * 100;
        setGetWidth(progressPercentage);
        setMusicPlayTime(formatTime(player.getCurrentTime()));
      }
    }, 100);

    return () => clearInterval(timer)
  }, []);

  useEffect(() => {
    // 键盘事件
    const keyIncident = (ev: KeyboardEvent) => {
      ev.preventDefault();
      switch (ev.key) {
        case "ArrowUp":
          previousTrack();
          break;
        case "ArrowDown":
          theNextSong();
          break;
        case "ArrowLeft":
          if (player.getCurrentTime() - 5 < 0) {
            player.seekTo(0);
            setMusicPlayTime(formatTime(0));
          } else {
            seek(-5);
          }
          break;
        case "ArrowRight":
          if (player.getCurrentTime() + 5 > player.getDuration()) {
            player.seekTo(player.getDuration());
            setMusicPlayTime(formatTime(player.getDuration()));
          } else {
            seek(5);
          }
          break;
        case "Enter":
          setIsPlay('play');
          player.play();
          onUpdateIsPlay && onUpdateIsPlay('play');
          break;
        case "Escape":
          navigate(`/musicList?isPlay=${isPlay}&musicId=${musicId}`);
          break;
        case " ":
          setIsPlay('pause');
          player.pause();
          onUpdateIsPlay && onUpdateIsPlay('pause');
          break;
      }
    };
    document.addEventListener("keydown", keyIncident);
    document.oncontextmenu = function (e) {
      e.preventDefault();
      return false;
    };
    return () => {
      document.removeEventListener("keydown", keyIncident);
      document.oncontextmenu = null;
    };
    // eslint-disable-next-line
  }, []);

  // 进度条时间更新
  const handleTimeUpdate = (time: number, dur: number) => {
    const progress = (time / dur) * 100;
    setGetWidth(progress);
    setMusicPlayTime(formatTime(time));
  };

  // 播放或暂停
  const playMusic = (value: string) => {
    setIsPlay(value);
    if (value === 'pause') {
      player.pause();
    } else {
      player.play();
      player.onTimeUpdate(handleTimeUpdate);
    }
    onUpdateIsPlay && onUpdateIsPlay(value);
  };

  // 拖拽、点击、长按等交互
  const handleClick = (e: any) => {
    if (!scheduleRef.current) return;
    const rect = scheduleRef.current.getBoundingClientRect();
    const x = e.windowX - rect.left;
    const currentProgress = (x / rect.width) * 100;
    if (currentProgress > 0 && currentProgress <= 100) {
      const newTime = (currentProgress * player.getDuration()) / 100;
      setGetWidth(currentProgress);
      player.seekTo(newTime);
      setMusicPlayTime(formatTime(newTime));
    }
  };

  // 上一曲
  const previousTrack = () => {
    player.pause();
    updateMusic(-1);
  };

  // 下一曲
  const theNextSong = () => {
    player.pause();
    updateMusic(1);
  };

  // 切歌
  const updateMusic = (num: number) => {
    const musicIndex = musicList.findIndex((item) => item.id === musicId);
    if (musicIndex === -1) return; // 如果 musicId 未找到，直接返回

    const newIndex = musicIndex + num;
    if (newIndex >= 0 && newIndex < musicList.length) {
      const nextMusic = musicList[newIndex];
      player.seekTo(0);
      player.play();
      player.onTimeUpdate(handleTimeUpdate);
      setIsPlay('play');
      setMusicId(nextMusic.id);
      onUpdateIsPlay && onUpdateIsPlay('play');
      onUpdateMusic && onUpdateMusic(nextMusic.id);
    }
  };

  // 快进快退
  const seek = (num: number) => {
    const newTime = player.getCurrentTime() + num;
    player.seekTo(newTime);
    setMusicPlayTime(formatTime(newTime));
  };

  const handleScrollStart = (e) => {
    const currentProgress = ((e.windowX - Number(startX.current)) / Number(scheduleWidth.current)) * 100;
    if (currentProgress > 0 && currentProgress <= 100) {
      const newTime = (currentProgress * player.getDuration()) / 100;
      setGetWidth(currentProgress);

      player.seekTo(newTime);
      setMusicPlayTime(formatTime(newTime));
    }
  }

  const progressMemo = useMemo(() => {
    return (
      <div className="progress-container" ref={progressRef as any} >
        <div className="progress-track" ref={scheduleRef as any} >
          <div className="progress-buffered" style={{ width: getWidth + '%' }}></div>
          <div className="progress-fill" style={{ width: getOffLeft + '%' }}></div>
        </div>
        <div className="time">
          <span className="current-time">{musicPlayTime}</span>
          <span className="duration">{musicTime}</span>
        </div>
      </div>
    )
  }, [getWidth, musicTime])


  return (
    <div className="player">
      <div className="time_schedule">
        {progressMemo}
      </div>
      <div className="play_icon">
        <img src={repeatIcon} alt="" />
        <img onClick={previousTrack} src={leftIcon} alt="" />
        {isPlay === 'play' ? (
          <img onClick={() => playMusic('pause')} src={pauseIcon} alt="" />
        ) : (
          <img onClick={() => playMusic('play')} src={playIcon} alt="" />
        )}
        <img onClick={theNextSong} src={forwardIcon} alt="" />
        <img src={noteListIcon} alt="" />
      </div>
      <div className="play_nav_icon">
        <img src={sharePlayIcon} alt="" />
        <img src={bellIcon} alt="" />
        <img src={arrowDownCircleIcon} alt="" />
        <img src={dotIcon} alt="" />
      </div>
    </div>
  );
};

export default MusicPlayer;